package com.hup.minicontroller.server.service;

import android.bluetooth.BluetoothAdapter;
import android.os.Build;
import android.os.Handler;
import android.util.Log;

import com.hup.minicontroller.common.bluetooth.BluetoothServer;
import com.hup.minicontroller.common.bluetooth.BluetoothServer.BtServerCallback;
import com.hup.minicontroller.common.bluetooth.BluetoothServer.BtServerConfig;
import com.hup.minicontroller.common.bluetooth.BluetoothServer.StartState;
import com.hup.minicontroller.common.bluetooth.framework.BtChannel;
import com.hup.minicontroller.common.bluetooth.handler.BtDataSplitCodecHandler;
import com.hup.minicontroller.common.bluetooth.handler.BtLoginHandler.BtLoginCallback;
import com.hup.minicontroller.common.bluetooth.handler.BtLoginHandler.BtLoginException;
import com.hup.minicontroller.common.bluetooth.handler.dataLIstener.BtNetSpeedListener;
import com.hup.minicontroller.common.constant.NetConstant.ConnectType;
import com.hup.minicontroller.common.framework.MainThreadHandler;
import com.hup.minicontroller.common.framework.SubThreadHandler;
import com.hup.minicontroller.common.model.dto.BtLoginResponse;
import com.hup.minicontroller.common.model.dto.LoginRequest;
import com.hup.minicontroller.common.netty.handler.LoginHandler.LoginException;
import com.hup.minicontroller.common.util.Assert;
import com.hup.minicontroller.server.R;
import com.hup.minicontroller.server.ServerApplication;
import com.hup.minicontroller.server.model.AppConfig;
import com.hup.minicontroller.server.model.AppState;
import com.hup.minicontroller.server.model.OnlineClientSession;
import com.hup.minicontroller.server.mvp.ICursorFloaterView;
import com.hup.minicontroller.server.mvp.IMainView;
import com.hup.minicontroller.server.mvp.IScreenImageService;
import com.hup.minicontroller.server.mvp.IServerHandler;

import java.util.Iterator;
import java.util.Locale;

import lombok.Getter;

/**
 * 蓝牙server,代码几乎是和LanServerService一样的
 */
public class BluetoothServerService implements IServerHandler {
    private static final String TAG = BluetoothServerService.class.getSimpleName();

    private final AppState appState;
    private final BluetoothServer server;
    private final BtNetSpeedListener netSpeedListener;

    @Getter
    private ConnectType connectType = ConnectType.BLUETOOTH;

    BluetoothServerService(AppState appState, DataRequestService dataRequestService, BluetoothAdapter bluetoothAdapter) {
        this.appState = appState;
        MyServerCallback serverCallback = new MyServerCallback();
        AppConfig appConfig = appState.getAppConfig();
        BtServerConfig serverConfig = new BtServerConfig(bluetoothAdapter, serverCallback, appConfig.getBtServerName(), appConfig.getBtUuid());
        serverConfig.setLoginCallback(serverCallback);
        serverConfig.setIdleCallback(() -> ServerApplication.getBean(SubThreadHandler.class));
        serverConfig.addDataHandler(dataRequestService);
        server = new BluetoothServer(serverConfig);
        netSpeedListener = new BtNetSpeedListener();
        BtDataSplitCodecHandler.INSTANCE.addDataListener(netSpeedListener);
        //BtDataSplitCodecHandler.INSTANCE.addDataListener(new BtPrintDataListener());//测试时打印数据
    }

    @Override
    public void switchServer(boolean isStart) {
        Log.i(TAG, "switchServer: " + isStart);
        if (isStart) {
            //此处可以加入自动蓝牙的业务
            server.startServer();
        } else {
            server.stopServer();
        }
    }

    @Override
    public void doTerminate() {
        Log.i(TAG, "doTerminate: ");
        if (StartState.STARTED.equals(server.getStartState())) {
            server.stopServer();
        }
    }

    @Override
    public void getSpeedText(StringBuilder sb) {
        if (server.getStartState() != StartState.STARTED) return;
        netSpeedListener.updateSpeed();
        if (sb.length() != 0) sb.append('\n');
        sb.append(String.format(Locale.getDefault(), "蓝牙  发送: %dKB/s, 接收: %dKB/s", netSpeedListener.getSendSpeed(), netSpeedListener.getReceiveSpeed()));
    }

    private class MyServerCallback implements BtServerCallback, BtLoginCallback<LoginRequest, BtLoginResponse> {

        @Override
        public void onServerStartResult(boolean success) {
            Log.i(TAG, "onServerStartResult: " + success);
            appState.setStartedBluetooth(success);
            ServerApplication.executeIfExist(IMainView.class, i -> i.onNetServerStateChanged(getConnectType()));
        }

        @Override
        public void onServerStopped() {
            Log.i(TAG, "onServerStopped: ");
            appState.setStartedBluetooth(false);
            appState.accessClient(clientSessions -> clientSessions.removeIf(session -> session.getConnectType() == ConnectType.BLUETOOTH));
            ServerApplication.executeIfExist(IMainView.class, i -> i.onNetServerStateChanged(getConnectType()));
            if (!MainService.SWITCH_SCREEN_ON_BOOT) {
                ServerApplication.executeIfExist(IScreenImageService.class, i -> i.switchService(appState.hasClient()));
            }
        }

        @Override
        public Handler getHandler() {
            return ServerApplication.getBean(SubThreadHandler.class);
        }

        @Override
        public Class<LoginRequest> getLoginRequestType() {
            return LoginRequest.class;
        }

        @Override
        public void doLoginValid(BtChannel btChannel, LoginRequest data) throws BtLoginException {
            Log.i(TAG, "doLoginValid: 按需校验认证" + data);
            try {
                Assert.hasText(data.getName(), () -> "用户名为空");
//                throw new IllegalAccessException("测试认证不通过");
            } catch (Exception e) {
                throw new LoginException(e.getMessage());
            }
        }

        @Override
        public BtLoginResponse getLoginSuccessResponse(BtChannel btChannel, LoginRequest loginReq) {
            Log.i(TAG, "getLoginSuccessResponse: 按需设计回复数据");
            return new BtLoginResponse(Build.MODEL, appState.getControlConfig().toDto());
        }

        @Override
        public void onClientConnectChanged(boolean onLine, BtChannel channel) {
            appState.accessClient(onlineClientSessions -> {
                Log.i(TAG, "onClientConnectChanged: onLine=" + onLine + ", channel=" + channel);
                if (onLine) {
                    LoginRequest loginRequest = (LoginRequest) channel.getLoginRequest();
                    OnlineClientSession session = OnlineClientSession.bluetooth(loginRequest, channel);
                    onlineClientSessions.add(session);
                    ServerApplication.getBean(MainThreadHandler.class).post(() ->
                            ServerApplication.executeIfExist(ICursorFloaterView.class, ICursorFloaterView::onClientOnline));
                } else {
                    if (StartState.STOPPED.equals(server.getStartState())) {
                        Log.i(TAG, "onClientConnectChanged: server关闭后,客户端下线事件");
                        //由onServerStopped更新session并通知ui
                        return;
                    }
                    Iterator<OnlineClientSession> it = onlineClientSessions.iterator();
                    while (it.hasNext()) {
                        if (channel.equals(it.next().getBtChannel())) {
                            it.remove();
                            break;
                        }
                    }
                }
                ServerApplication.executeIfExist(SoundService.class, s -> s.play(onLine ? R.raw.online : R.raw.offline));
                ServerApplication.executeIfExist(IMainView.class, IMainView::onClientChanged);
                if (!MainService.SWITCH_SCREEN_ON_BOOT) {
                    ServerApplication.executeIfExist(IScreenImageService.class, i -> i.switchService(appState.hasClient()));
                }
            });
        }
    }

}
